package black.market.database;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import android.app.ListActivity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import black.market.main.BlackPublic;
import black.market.main.R;
import dalvik.system.DexClassLoader;

public class DatabaseActivity extends ListActivity {
	public static final String TAG = "DatabaseActivity";
	private ArrayAdapter<String> mAdapter = null;
	private String[] labelArr = null;
	private Drawable[] iconArr = null;
	private ArrayList<ProviderInfo[]> providerInfoArrList = null;

	public void otherAppDatabase() {
		PackageManager manager = getPackageManager();
		List<PackageInfo> packageList = manager.getInstalledPackages(PackageManager.GET_PROVIDERS);
		for (int i = 0; i < packageList.size(); i++) {
			String packageName = packageList.get(i).packageName;
			BlackPublic.debugLog(TAG, "package List: " + packageList.get(i).packageName);
			Context con = null;
			Cursor c = null;
			try {
				con = createPackageContext(packageName, Context.CONTEXT_IGNORE_SECURITY);
				ProviderInfo[] piArr = packageList.get(i).providers;
				if (piArr != null) {
					for (int t = 0; t < piArr.length; t++) {
						DexClassLoader dexLoader = getDexClassLoader(piArr[t].applicationInfo.sourceDir);
						Uri u = getUriField(dexLoader.loadClass(piArr[t].name));
						BlackPublic.debugLog(TAG, "package Uri: " + u);
						ContentResolver cr = con.getContentResolver();
						c = cr.query(u, null, null, null, null);
						if (c.getCount() > 0 || c != null) {
							BlackPublic.debugLog(TAG, "Cursor cnt: " + c.getCount());
							String[] cNameArr = c.getColumnNames();
							BlackPublic.debugLog(TAG, "col  length: " + cNameArr.length);
							while (c.moveToNext()) {
								for (int k = 0; k < cNameArr.length; k++) {
									BlackPublic.debugLog(TAG, cNameArr[k] + "----> " + c.getString(c.getColumnIndex(cNameArr[k])));
								}
							}
						}
						c.close();
					}
				}
			} catch (NameNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public void testPackageManager() {
		PackageManager pm = getPackageManager();
		try {
			List<PermissionInfo> infos = pm.queryPermissionsByGroup(null, 0);
			for (int i = 0; i < infos.size(); i++) {
				BlackPublic.debugLog("TEST", "PermissionInfo.group: " + infos.get(i).group);
				BlackPublic.debugLog("TEST", "PermissionInfo.name: " + infos.get(i).name);
			}
		} catch (NameNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void addReadWritePermission(ProviderInfo pi) throws NameNotFoundException, SecurityException, IllegalArgumentException,
			NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
		Context con = createPackageContext(pi.packageName, CONTEXT_IGNORE_SECURITY);

		String[] dbArr = con.databaseList();
		BlackPublic.debugLog(TAG, "con name: " + con.getPackageName());
		BlackPublic.debugLog(TAG, "dbList len: " + dbArr.length);
		for (int i = 0; i < dbArr.length; i++) {
			BlackPublic.debugLog(TAG, "dbList[" + i + "]: " + dbArr[i]);
		}
		// BlackPublic.debugLog(TAG, "con : " + con.getPackageName());
		//
		// PackageManager manager = con.getPackageManager();
		// PermissionInfo permissionInfo =
		// manager.getPermissionInfo(pi.readPermission, 0);
		// BlackPublic.debugLog(TAG, "permission.descriptionRes: " +
		// permissionInfo.descriptionRes);
		// BlackPublic.debugLog(TAG, "permission.protectionLevel: " +
		// permissionInfo.protectionLevel);
		// BlackPublic.debugLog(TAG, "permission.labelRes: " +
		// permissionInfo.labelRes);
		// BlackPublic.debugLog(TAG, "permission.name: " + permissionInfo.name);
		// BlackPublic.debugLog(TAG, "permission.packageName: " +
		// permissionInfo.packageName);
		//
		// manager.addPermission(manager.getPermissionInfo(pi.readPermission,
		// 0));
		// DexClassLoader dexLoader =
		// getDexClassLoader(pi.applicationInfo.sourceDir);
		// Cursor c =
		// con.getContentResolver().query(getUriField(dexLoader.loadClass(pi.name)),
		// null, null, null, null);
		// BlackPublic.debugLog(TAG, "otherContext URI : " +
		// getUriField(dexLoader.loadClass(pi.name)));
		// BlackPublic.debugLog(TAG, "otherContext : " + c.getCount());
		// c.close();
		// BlackPublic.debugLog(TAG, "Context : " + con.getPackageName());
		// BlackPublic.debugLog(TAG, "PackageManager : " +
		// manager.getPermissionInfo(pi.readPermission, 0).packageName);
		//
		// PermissionInfo in = manager.getPermissionInfo(pi.readPermission,
		// PackageManager.GET_META_DATA);
		// BlackPublic.debugLog(TAG, "in.protectionLevel: " +
		// in.protectionLevel);
		// BlackPublic.debugLog(TAG, "in.packageName: " + in.packageName);
		// BlackPublic.debugLog(TAG, "in.name: " + in.name);
		// manager.addPermission(manager.getPermissionInfo(pi.readPermission,
		// PackageManager.GET_META_DATA));
		//
		// manager.addPermission(manager.getPermissionInfo(pi.writePermission,
		// PackageManager.GET_META_DATA));
	}

	public void selectProviderInfo(ProviderInfo pi) {
		BlackPublic.debugLog("TEST", "pi.readPermission: " + pi.readPermission);
		BlackPublic.debugLog("TEST", "pi.writePermission: " + pi.writePermission);

		PackageManager manager = getPackageManager();
		try {
			PermissionInfo info = manager.getPermissionInfo(pi.readPermission, 0);
			BlackPublic.debugLog("TEST", "info.name: " + info.name);
		} catch (NameNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		selectApplicationInfo(pi.applicationInfo);
	}

	public void selectApplicationInfo(ApplicationInfo ai) {
		BlackPublic.debugLog("TEST", "ai.permission: " + ai.permission);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		providerInfoArrList = new ArrayList<ProviderInfo[]>();
		providerInfoArrList = getPackage_Providers_Info();
		labelArr = new String[providerInfoArrList.size()];
		iconArr = new Drawable[providerInfoArrList.size()];
		// otherAppDatabase();
		for (int i = 0; i < providerInfoArrList.size(); i++) {
			labelArr[i] = providerLabel(providerInfoArrList.get(i)[0]);
			iconArr[i] = providerIcon(providerInfoArrList.get(i)[0]);
			try {
				ProviderInfo[] piArr = providerInfoArrList.get(i);
				for (int j = 0; j < piArr.length; j++) {
					ProviderInfo pi = piArr[j];
					String str = pi.applicationInfo.packageName;
					BlackPublic.debugLog(TAG, "applicationInfo.className: " + str);
					// addReadWritePermission(pi);

					// addReadWritePermission(pi);
					// selectProviderInfo(pi);
					// DexClassLoader dexLoader =
					// getDexClassLoader(pi.applicationInfo.sourceDir);
					// Class c = dexLoader.loadClass(pi.name);
					// Object obj = c.newInstance();
					// getPackage_DatabaseList(getUriField(dexLoader.loadClass(pi.name)));
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		setContentView(R.layout.database_main);
		mAdapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.list_line_item1, labelArr);
		setListAdapter(mAdapter);
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();

	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		// TODO Auto-generated method stub
		super.onListItemClick(l, v, position, id);
	}

	private DexClassLoader getDexClassLoader(String dexPath) {
		String dexOutputDir = Environment.getExternalStorageDirectory().getAbsolutePath();
		String libPath = null;
		return new DexClassLoader(dexPath, dexOutputDir, libPath, ClassLoader.getSystemClassLoader().getParent());
	}

	public Uri getUriField(Class<?> c) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
		Uri res = null;
		Field[] fields = c.getFields();
		for (int k = 0; k < fields.length; k++) {
			Type fieldType = fields[k].getGenericType();
			Type uriType = Uri.class;
			if (fieldType.equals(uriType)) {
				String fName = fields[k].getName();
				Field uriField = c.getField(fName);
				Object uriObj = uriField.get(c);
				if (uriObj instanceof Uri) {
					BlackPublic.debugLog(TAG, "Uri Field uriObj -> " + uriObj);
					res = (Uri) uriObj;
				} else {
					BlackPublic.debugLog(TAG, "uriObj is Not Uri Class Type");
				}
			} else {
				BlackPublic.debugLog(TAG, fieldType + "and " + uriType + " Type is even");
			}
		}
		return res;
	}

	public void getPackage_DatabaseList(Uri uri) {
		int columnCnt = 0;
		String[] colNames = null;
		String[] projection = null;
		String selection = null;
		String[] selectionArgs = null;
		String sortOrder = null;
		Cursor c = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
		if (c.getCount() > 0) {
			columnCnt = c.getColumnCount();
			colNames = c.getColumnNames();
			for (int i = 0; i < columnCnt; i++) {
				BlackPublic.debugLog(TAG, "getPackageDB colNamse -> " + colNames[i]);
			}
		} else {
			BlackPublic.debugLog(TAG, "Uri" + uri + " Cursor is 0");
		}
	}

	public String providerLabel(ProviderInfo pi) {
		BlackPublic.debugLog(TAG, "Provider Label -> " + (String) pi.loadLabel(getPackageManager()));
		return (String) pi.loadLabel(getPackageManager());
	}

	public Drawable providerIcon(ProviderInfo pi) {
		BlackPublic.debugLog(TAG, "Provider Label -> " + (String) pi.loadLabel(getPackageManager()));
		return pi.loadIcon(getPackageManager());
	}

	public ArrayList<ProviderInfo[]> getPackage_Providers_Info() {
		PackageManager pm = getPackageManager();
		List<PackageInfo> packageInfoList = pm.getInstalledPackages(PackageManager.GET_PROVIDERS);
		ArrayList<ProviderInfo[]> arrayList = null;
		if (packageInfoList.size() > 0) {
			arrayList = new ArrayList<ProviderInfo[]>();
			for (int i = 0; i < packageInfoList.size(); i++) {
				ProviderInfo[] piArr = packageInfoList.get(i).providers;
				if (piArr == null) {
					BlackPublic.debugLog(TAG, "GET_PROVIDERS is null");
				} else {
					String str = (String) piArr[0].loadLabel(pm);
					BlackPublic.debugLog(TAG, "Label : " + str);
					arrayList.add(piArr);
				}
			}
		} else {
			BlackPublic.debugLog(TAG, "packageInfoList is null");
		}
		return arrayList;
	}

	public Uri getProvidersUri(ProviderInfo pi) throws Exception {
		Uri res = null;
		ApplicationInfo ai = pi.applicationInfo;
		String dexPath = ai.sourceDir;
		String dexOutputDir = "/sdcard";
		String libPath = null;
		ClassLoader parent = ClassLoader.getSystemClassLoader();
		DexClassLoader dexClassLoader = new DexClassLoader(dexPath, dexOutputDir, libPath, parent);
		Class<?> c = dexClassLoader.loadClass(ai.className);
		Field[] fields = c.getFields();
		for (int k = 0; k < fields.length; k++) {
			Type fieldType = fields[k].getGenericType();
			Type uriType = Uri.class;
			if (fieldType.equals(uriType)) {
				String fName = fields[k].getName();
				Field uriField = c.getField(fName);
				Object uriObj = uriField.get(c);
				if (uriObj instanceof Uri) {
					BlackPublic.debugLog(TAG, "Uri Field uriObj -> " + uriObj);
					res = (Uri) uriObj;
				} else {
					BlackPublic.debugLog(TAG, "uriObj is Not Uri Class Type");
				}
			} else {
				BlackPublic.debugLog(TAG, fieldType + "and " + uriType + " Type is even");
			}
		}
		return res;
	}

	public Uri getProviderClassUriField() throws ClassNotFoundException, SecurityException, NoSuchFieldException, IllegalArgumentException,
			IllegalAccessException {
		Uri res = null;
		PackageManager pm = getPackageManager();
		ArrayList<PackageInfo> piList = (ArrayList<PackageInfo>) pm.getInstalledPackages(PackageManager.GET_PROVIDERS);
		for (int i = 0; i < piList.size(); i++) {
			ProviderInfo[] piArr = piList.get(i).providers;
			if (piArr == null) {
				BlackPublic.debugLog(TAG, "ProviderInfo is null");
			} else {
				for (int j = 0; j < piArr.length; j++) {
					BlackPublic.debugLog(TAG, "Provider info packageName authority= " + piArr[j].authority);
					BlackPublic.debugLog(TAG, "Provider info packageName name= " + piArr[j].name);
					String className = piArr[j].authority;
					ClassLoader classLoader = getClassLoader();
					BlackPublic.debugLog(TAG, "classloader2: " + classLoader.toString());
					Class<?> c = classLoader.loadClass(className);
					Field[] fields = c.getFields();
					for (int k = 0; k < fields.length; k++) {
						Type fieldType = fields[k].getGenericType();
						Type uriType = Uri.class;
						if (fieldType.equals(uriType)) {
							String fName = fields[k].getName();
							Field uriField = c.getField(fName);
							Object uriObj = uriField.get(c);
							if (uriObj instanceof Uri) {
								BlackPublic.debugLog(TAG, "Uri Field uriObj -> " + uriObj);
								res = (Uri) uriObj;
							} else {
								BlackPublic.debugLog(TAG, "uriObj is Not Uri Class Type");
							}
						} else {
							BlackPublic.debugLog(TAG, fieldType + "and " + uriType + " Type is even");
						}
					}
				}
			}
		}
		return res;
	}
}
